#pragma once
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include "Common.hpp"
#include "connection.hpp"
#include"HandlerConnection.hpp"

/*这个类的逻辑就是，我们在main外部实现了listen套接字的链接，接着就是需要
对后续的通信套接字进行接收，并且实现对应的函数，进入连接中*/

class Accepter     // 本质上就是Tcp的accept的封装，也就是对listen_sock关心的事件就绪进行处理
{
public:
    Accepter() {}
    ~Accepter() {}
    void AcceptConnection(Connection *conn) // listen套接字获取新套接字
    {
        // ET模式下需要不断的进行轮询读取，需要在外部对listen套接字设置非阻塞读取
        while (1)
        {
            struct sockaddr_in peer;
            // conn->SetClient(peer); 可以将客户端信息获取到连接中
            socklen_t len = sizeof(peer);
            int sock_fd = accept(conn->GetSockFd(), (struct sockaddr *)&peer, &len);
            if (sock_fd > 0)
            {
                lg.LogMessage(Info, "get a new link, fd = %d\n", sock_fd);

                // 获取到新的套接字，进行epoll等待
                // conn->_ts->AddConnection(conn);

                // ET模式下需要对这个描述符设置为非阻塞
                SetNoneBlock(sock_fd);

                // 获取IO实现函数
                auto recver = std::bind(&HandlerConnection::Recver, std::placeholders::_1);
                auto sender = std::bind(&HandlerConnection::Sender, std::placeholders::_1);
                auto excepter = std::bind(&HandlerConnection::Excepter, std::placeholders::_1);
                // 构建普通的套接字
                Connection *normal_conn = ConnectionFactory::BulidSockConnection(sock_fd, recver, sender, excepter, EPOLLIN | EPOLLET, conn->_R);
                // 通过TCP指针来进行回调，将连接添加到Reactor中
                conn->_R->AddConnection(normal_conn);
            }
            else
            {
                if (errno == EAGAIN)
                    break;
                else if (errno == EINTR)
                    continue;
                else
                {
                    lg.LogMessage(Warning, "get a new link failed");
                    break;
                }
            }
        }
    }

private:
};